﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;

namespace Kokomo.Xml
{
	public class AssemblyBasedNamespace : NamespaceSchema
	{
		protected static Uri GetUri(
			Assembly assembly,
			string assemblyNamespace)
		{
			ArgumentValidation.CheckNullArgument("assembly", assembly);

			Uri uri = new Uri(string.Format("clr-namespace:{0};{1}", assemblyNamespace, assembly.GetName().Name));

			return uri;
		}

		public AssemblyBasedNamespace(
			string name,
			Assembly assembly,
			string assemblyNamespace)
			: base(name, GetUri(assembly, assemblyNamespace))
		{
			ArgumentValidation.CheckNullArgument("assembly", assembly);
			ArgumentValidation.CheckNullArgument("assemblyNamespace", assemblyNamespace);

			this.Assembly = assembly;
			this.AssemblyNamespace = assemblyNamespace;
		}

		public Assembly Assembly { get; private set; }
		public string AssemblyNamespace { get; private set; }
		public List<TypeSchema> TypeSchemas { get; private set; }

		protected override TypeSchema GetTypeSchemaCore(string elementName)
		{
			TypeSchema matchSchema = null;
			foreach (var schema in this.TypeSchemas)
			{
				if (schema.ElementName == elementName)
				{
					matchSchema = schema;
					break;
				}
			}

			if (matchSchema == null)
			{
				string fullTypeName = string.Format("{0}.{1}", this.AssemblyNamespace, elementName);
				Type type = this.Assembly.GetType(fullTypeName, false);
				matchSchema = new TypeSchema(type, type.Name);
			}

			return matchSchema;
		}
		protected override TypeSchema GetTypeSchemaCore(Type type)
		{
			if ((type.Namespace != this.AssemblyNamespace)
				|| (type.Assembly != this.Assembly)
				)
			{
				return null;
			}

			TypeSchema matchSchema = null;
			foreach (var schema in this.TypeSchemas)
			{
				if (schema.Type == type)
				{
					matchSchema = schema;
					break;
				}
			}

			if (matchSchema == null)
			{
				matchSchema = new TypeSchema(type, type.Name);
			}

			return matchSchema;
		}
	}
}
